<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Sudoku Solver</title>
    <link
      rel="stylesheet"
      href="https://unpkg.com/poplar-css@latest/dist/poplar.css"
    />
    <style>
      .puzzle {
        display: grid;
        grid-template-columns: 36px auto 108px 1fr;
        grid-template-rows: 36px auto;
      }
      .grid {
        position: relative;
        width: 324px;
      }
      .grid .lr::before,
      .grid .lr::after {
        background-color: #666;
        content: "";
        height: 2px;
        width: 100%;
        position: absolute;
        left: 0;
        top: 33.33%;
      }
      .grid .lr::after {
        top: 66.66%;
      }
      .grid .tb::before,
      .grid .tb::after {
        background-color: #666;
        content: "";
        height: 100%;
        width: 2px;
        position: absolute;
        left: 33.33%;
        top: 0;
      }
      .grid .tb::after {
        left: 66.66%;
      }
      .head {
        font-size: 15px;
        font-weight: bolder;
        height: 36px;
        width: 36px;
      }
      .cell {
        border: 1px solid #ccc;
        box-sizing: border-box;
        height: 36px;
        width: 36px;
      }
      .small {
        color: #666;
        height: 33.33%;
        line-height: 1;
        width: 33.33%;
      }
      .large {
        font-size: 16px;
        font-weight: bolder;
        height: 100%;
        width: 100%;
        position: relative;
      }
      .index {
        position: absolute;
        right: 0;
        top: 0;
        font-size: 18px;
        font-weight: normal;
        line-height: 24px;
        color: #000;
        transform: scale(0.5);
        transform-origin: right top;
        height: 24px;
        width: 24px;
        background-color: rgba(255, 0, 0, 0.3);
        border-bottom-left-radius: 50%;
      }

      .button {
        padding-left: 10px;
      }
      .button [class^="button"] {
        margin-bottom: 10px;
      }
    </style>
  </head>
  <body>
    <div id="root"></div>

    <script src="sudoku2.js"></script>
    <script src="puzzles.js"></script>
    <script>
      // puzzles.forEach(item => console.log(new Sudoku(item)))
    </script>
    <script
      src="https://unpkg.com/react/umd/react.development.js"
      crossorigin
    ></script>
    <script
      src="https://unpkg.com/react-dom/umd/react-dom.development.js"
      crossorigin
    ></script>
    <script src="https://unpkg.com/babel-standalone/babel.min.js"></script>
    <script type="text/babel">
      const { Fragment, useState, useEffect, useCallback } = React;

      let sudoku = null;

      const App = () => {
        const [grid, setGrid] = useState([]);
        const [current, setCurrent] = useState(-1);
        const [active, setActive] = useState([]);

        useEffect(() => {
          sudoku = new Sudoku(puzzles[0]);
          setGrid(sudoku.grid.slice());
        }, []);

        // 显式唯一法
        const handleNakedSingle = () => {
          const current = sudoku.nakedSingle();
          if (current === -1) {
            console.log("显式唯一法：没有合适的解");
          } else {
            setGrid(sudoku.grid.slice());

            const step = sudoku.steps[current];
            const value = sudoku.grid[current];
            setCurrent(value);
            setActive(step.other);
            console.log(
              step.index +
                ". " +
                sudoku.getCellNamed(current) +
                "单元格使用显式唯一法得到解：" +
                value
            );
          }
        };
        // 隐式唯一法
        const handleHiddenSingle = () => {
          const current = sudoku.hiddenSingle();
          if (current === -1) {
            console.log("隐式唯一法：没有合适的解");
          } else {
            setGrid(sudoku.grid.slice());

            const step = sudoku.steps[current];
            const value = sudoku.grid[current];
            setCurrent(value);
            setActive(step.other);
            console.log(
              step.index +
                ". " +
                sudoku.getCellNamed(current) +
                "单元格使用隐式唯一法得到解：" +
                value
            );
            console.log(
              step.other.map((v) => sudoku.getCellNamed(v)).join("/") +
                " 均不可以填入数字" +
                value
            );
          }
        };
        // 区块删减法
        const handleIntersectionRemoval = () => {
          sudoku.intersectionRemoval();
          setGrid(sudoku.grid.slice());
        };

        return (
          <div className="puzzle text-xs">
            <div></div>
            <div className="flex">
              {Array(9)
                .fill()
                .map((v, i) => (
                  <div
                    key={i}
                    className="head flex main-content-center cross-items-center"
                  >
                    {i + 1}
                  </div>
                ))}
            </div>
            <div></div>
            <div></div>

            <div className="flex flex-column">
              {"ABCDEFGHI".split("").map((v) => (
                <div
                  key={v}
                  className="head flex main-content-center cross-items-center"
                >
                  {v}
                </div>
              ))}
            </div>
            <div className="grid flex flex-wrap">
              {grid.map((cell, i) => (
                <div
                  key={i}
                  className="cell flex flex-wrap"
                  style={{
                    backgroundColor: active.includes(i) ? "#e8e8e8" : "",
                  }}
                >
                  {Array.isArray(cell) ? (
                    <Fragment>
                      {Array(9)
                        .fill()
                        .map((v, j) => (
                          <div
                            key={j}
                            className="small flex main-content-center cross-items-center"
                            style={{ display: "block" }}
                          >
                            {cell.includes(j + 1) ? j + 1 : ""}
                          </div>
                        ))}
                    </Fragment>
                  ) : (
                    <div
                      className="large flex main-content-center cross-items-center"
                      style={{ color: current === cell ? "red" : "" }}
                    >
                      {cell || ""}
                      {sudoku && sudoku.steps[i].index > 0 && (
                        <div className="index flex main-content-center cross-items-center">
                          {sudoku.steps[i].index}
                        </div>
                      )}
                    </div>
                  )}
                </div>
              ))}
              <div className="lr"></div>
              <div className="tb"></div>
            </div>
            <div className="button">
              <button
                className="button-black button-sm radius-sm"
                onClick={handleNakedSingle}
              >
                显式唯一法
              </button>
              <button
                className="button-black button-sm radius-sm"
                onClick={handleHiddenSingle}
              >
                隐式唯一法
              </button>
              <button
                className="button-black button-sm radius-sm"
                onClick={handleIntersectionRemoval}
              >
                区块删减法
              </button>
            </div>
          </div>
        );
      };

      ReactDOM.render(<App />, document.querySelector("#root"));
    </script>
  </body>
</html>
